## Class for SIPC Data Package
## Author : Wenpeng WEI ( mailto: wenpeng.wei[at]gmail.com )
## 2009/11/18

class SIPCPackage
  
  attr_accessor :event, :domain, :code, :code_text, :head, :body
  
  def initialize ( package = "" )
    if package == ""
      @head = {}
      return 
    end
    lines = package.lines.to_a
    line1 = lines[0].split
    last_line = lines[-1]
    @body = last_line.chomp
    lines = lines[1..-2]
    if line1[0] != "SIP-C/2.0"
      @event = line1[0]
      @domain = line1[1]
      @code = "0"
      @code_text = ""
    else
      @event = "response"
      @domain = ""  
      @code = line1[1]
      @code_text = line1[2]
    end
    @head = {}
    lines.each do |line|
      if line != "\r\n" && line != "" && line != nil
        if line.include? ":"
          pair = line.split(": ")
          @head[pair[0]] = pair[1].chomp
        end
      end
    end
    
  end
  
  def to_package
    package = ""
    if @event == "response"
      package += "SIP-C/2.0 #{code} #{code_text}\r\n"
    else
      package += "#{event} #{domain} SIP-C/2.0\r\n"
    end
    head.each do | key, value |
      package += "#{key}: #{value}\r\n"
    end
    package += "\r\n#{body}"
    return package
  end
  
  def to_log
    return "------------\n#{to_package}\n-----------"
  end
  
  def from_package package
    if !(package.include?("SIP-C/2.0"))
      @@buffer = @@buffer + package.chomp
      package = @@buffer
    end
    
    lines = package.lines.to_a
    line1 = lines[0].split
    last_line = lines[-1]
    @body = last_line.chomp
    lines = lines[1..-2]
    if line1[0] != "SIP-C/2.0"
      @event = line1[0]
      @domain = line1[1]
      @code = "0"
      @code_text = ""
    else
      @event = "response"
      @domain = ""  
      @code = line1[1]
      @code_text = line1[2]
    end
    @head = {}
    lines.each do |line|
      if line != "\r\n" && line != "" && line != nil
        if line.include? ":"
          pair = line.split(": ")
          @head[pair[0]] = pair[1].chomp
        end
      end
    end
      
    if @head["L"].to_i == @body.chomp.size
      return true
    else
      @@buffer = package.chomp
      return false
    end
    
  end
  
  def parse package, *args, &action
    #puts package.scan("\r\n\r\n").size
    if action == nil && args != nil
      action = args[0]
    end
    if !(package.scan("\r\n\r\n").size > 1)
      p1 = SIPCPackage.new
      if p1.from_package(package)
        action.call(p1)
      end
    else
      nap = first_nap(package)
      if nap == nil
        parse package, action
      else
        parse package[0...nap], action
        parse package[nap..-1], action
      end
        
    end
  end
  
  def first_nap str
    r1 = str =~ /SIP-C\/2.0 \d\d\d \w+.*\r\n/
    r2 = str =~ /\w+ .+ SIP-C\/2.0.*\r\n/
    if r1==nil && r2 ==nil
      return nil
    elsif r1 == nil && r2 != nil
      if r2 == 0
        return ( str[1..-1] =~ /\w+ .+ SIP-C\/2.0.*\r\n/ ) +1
      else
        return r2
      end
    elsif r1 != nil && r2 == nil
      if r1 == 0
        return ( str[1..-1] =~ /SIP-C\/2.0 \d\d\d \w+.*\r\n/ ) +1
      else
        return r1
      end
    elsif r1 != nil && r2 != nil
      if r1 != 0 && r2 != 0
        return [r1, r2].min
      elsif r1 == 0 && r2 != 0
        r1 =  str[1..-1] =~ /SIP-C\/2.0 \d\d\d \w+.*\r\n/ 
        if r1 == nil
          return r2
        else
          return [r1+1, r2].min
        end
      elsif r1 != 0 && r2 == 0
        r2 = str[1..-1] =~ /\w+ .+ SIP-C\/2.0.*\r\n/ 
        if r2 == nil
          return r1
        else
          return [r1, r2+1].min
        end
      end
    end
  end
   
end